/**
Copyright 2011 Kathryn Neugent

This file is part of Joggle.

Joggle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Joggle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Joggle.  If not, see <http://www.gnu.org/licenses/>.
 */
package edu.gwu.cs.joggle;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;

/**
 * @author Kathryn Neugent <kathrynneugent@gmail.com>
 * @version 1
 * @since 2011-12-20
 */

public class Board implements ActionListener {

	protected char[][] vals; 				// characters on board
	protected int size; 					// length and width of board
	protected Game game;					// the Game that generated this Board
	protected String playerName;			// the username of the Player playing this Board
	protected String fndWords;				// words found on the Board by playerName
	protected JTextArea wordsFoundTxt;
	protected JTextArea wordGuessedTxt;
	protected JFrame frame;
	protected JCheckBox audit;

	/**
	 * Returns an ArrayList<String> of the words found on this board
	 * @return ArrayList<String>
	 */
	protected String getFndWords() {
		// check to make sure it was the server (not a malicious client) that asked for my word list
		if(game.getServer().verifyWordListCollect(game)) {
			return fndWords;
		} else {
			System.out.println("There was no record of the Server's request for my word list.  Not reporting.");
			return null;
		}
	}

	/**
	 * generates a board based on the values and size of the board
	 * @param boardVals The letters on the board
	 * @param size The length and width of the board
	 */
	public Board (char[][] boardVals, int s, Game g, String pName) {
		vals = boardVals;
		size = s;
		game = g;
		playerName = pName;
		fndWords = playerName;
		
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}

	/**
	 * Prints a representation of the board
	 */
	protected void printBoard() {
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				System.out.print(vals[x][y] + "\t");
			}
			System.out.println();
		}
		System.out.println();
	}

	public void createAndShowGUI() {
		// Set up the window
		frame = new JFrame("Joggle Board");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(320,340);

		// Set up content pane
		addComponentsToPane(frame.getContentPane());

		// Display the window
		frame.setVisible(true);
	}

	/**
	 * @param pane Container pane
	 */
	public void addComponentsToPane(Container pane) {
		// set layout
		pane.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.insets = new Insets(10,10,10,10);

		// Joggle banner
		JLabel banner = new JLabel(new ImageIcon(getClass().getResource("/assets/images/JoggleBanner.png")));
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 2;
		pane.add(banner,c);

		// add the game letters
		JPanel letterPanel = new JPanel();
		letterPanel.setLayout(new GridLayout(size,size));
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				JLabel letter = new JLabel(((Character)vals[x][y]).toString(),JLabel.CENTER);
				letter.setFont(new Font("Dialog",1,30));
				letterPanel.add(letter);
			}
		}
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		c.gridheight = 2;
		pane.add(letterPanel,c);

		// add the words found
		wordsFoundTxt = new JTextArea("   **WORDS FOUND**\n");
		wordsFoundTxt.setEditable(false);
		JScrollPane wordsFound = new JScrollPane(wordsFoundTxt);
		wordsFound.setPreferredSize(new Dimension(120,100));
		c.gridx = 1;
		c.gridy = 1;
		c.gridwidth = 1;
		c.gridheight = 1;
		pane.add(wordsFound,c);

		// audit box
		audit = new JCheckBox("mark for audit");
		audit.addActionListener(this);
		c.gridx = 1;
		c.gridy = 2;
		pane.add(audit,c);

		// type in guess
		wordGuessedTxt = new JTextArea();
		c.gridx = 0;
		c.gridy = 3;
		pane.add(wordGuessedTxt,c);

		// submit guess
		JButton submit = new JButton("submit!");
		submit.addActionListener(this);
		c.gridx = 1;
		c.gridy = 3;
		pane.add(submit,c);

	}

	// if submit button is clicked
	/**
	 * @param e ActionEvent for when the submit button is pressed
	 */
	public void actionPerformed(ActionEvent e) {
		String wrd = wordGuessedTxt.getText();

		// check to see if the word is valid
		//  FIND WORD IN GAME
		Boolean isThere = isWordThere(wrd);

		if (isThere) {
			wordsFoundTxt.append(wrd+" \n");
			fndWords += "#" + wrd;
		} else {
			System.out.println(wrd + " is not on the game board.");
		}
		wordGuessedTxt.setText("");
		boolean auditSel = audit.isSelected();
		if(auditSel) {
			game.setNumComplaints(game.getNumComplaints()+1);
		}
		//System.out.println("Audit this game? " + auditSel);
	}

	/**
	 * @param wrd String to be found in the board
	 * @return boolean True if the word is on the board, false otherwise
	 */
	protected Boolean isWordThere(String wrd) {
		// break wrd into a char array
		wrd = wrd.toUpperCase();
		char[] wrdC = wrd.toCharArray();
		Boolean isThere = false;

		int i = 0;
		Boolean next = true;
		while ((next) && (i < wrdC.length-1)) {
			next = nextTo(wrdC[i],wrdC[i+1]);
			i++;
		}
		if (i == wrdC.length-1)
			isThere = true;

		return isThere;
	}

	/**
	 * @param x char in word
	 * @param x next char in word
	 * @return boolean True if the letter y is next to the letter x on the board
	 */
	protected Boolean nextTo(char x, char y) {
		// next = down or right
		Boolean nextTo = false;

		// find char x in vals
		for (int i = 0; i < vals.length; i++) {
			for (int j = 0; j < vals[1].length; j++) {
				if (vals[i][j] == x) {
					// found the char

					// check below
					if ((j < vals[1].length-1) && (vals[i][j+1] == y)) {
						nextTo = true;

						// check above
					} else if ((j > 1) && (vals[i][j-1] == y)) {
						nextTo = true;

						// check to the right
					} else if ((i < vals.length-1) && (vals[i+1][j] == y)) {
						nextTo = true;

						// check to the left
					} else if ((i > 1) && (vals[i-1][j] == y)) {
						nextTo = true;

						// check diagonal upper left
					} else if ((i > 1) && (j > 1) && (vals[i-1][j-1] == y)) {
						nextTo = true;

						// check diagonal upper right
					} else if ((i < vals.length-1) && (j > 1) && (vals[i+1][j-1] == y)) {
						nextTo = true;

						// check diagonal lower left
					} else if ((i > 1) && (j < vals[1].length-1) && (vals[i-1][j+1] == y)) {
						nextTo = true;

						// check diagonal lower right
					} else if ((i < vals.length-1) && (j < vals[1].length-1) && (vals[i+1][j+1] == y)) {
						nextTo = true;
					}
				}
			}
		}
		return nextTo;
	}
}
